package com.yanqu.road.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class ClientDesUtil {

    private static Logger logger = LogManager.getLogger(ClientDesUtil.class.getName());

    // 客户端给的key
    private static final String clientKey = "12468";

    public static void main(String[] args) {
        long time = System.currentTimeMillis();

        /*
        // 【自己测试加解密】
        String packageId = "33";
        String content = "{\n  \"pVersion\" : \"4.7.912\",\n  \"rVersion\" : \"4.7.12\",\n  \"packageMark\" : \"261002033\"\n}";

        String jiaMiResult = jiaMi(packageId, content);
        System.err.println("加密结果：");
        System.err.println(jiaMiResult);

        if (jiaMiResult != null) {
            String jieMiResult = jieMi(packageId + '/' + jiaMiResult);
            System.err.println("解密结果：");
            System.err.println(jieMiResult);
        }
        */


        // 【测试解密客户端数据】
        String param = "22/zlZ3BVW88wURRUpNkVlxQBHOoPEfvUAWTjBfqeXLshmvVa542/5K1gR1UcAv7DnN3iEzg39lw2A3Qx+162NUHFdUDpo7KUGjR8xVA9yM1uHyvFuZTfEN+DgIZghIDimCIDc7Oof+VT0NGB3hBatsSdw2KZxykXllSAjIIRQkiMb1obiben1YhBPTSH25E0DZvUBnc013aWkGsyGUmv/8/aFSjd9wW+wMQZ3Bfhb0dR71Us9jWpzDfAH5akf0DGswTnL8wc5k+0R8QSGfZGU01/ptLCIl+fjDrJ/kEZkzy0BnWxSWC0Tjovu9WUjwBzKUAsBHtCCsVZIcsPPo97q8YenLi9d5oYiy1pmUi2v8a/k=";
        String jieMiResult = jieMi(param);
        System.err.println("解密结果：");
        System.err.println(jieMiResult);


        System.err.println("耗时： " + (System.currentTimeMillis() - time) + " ms");
    }

    /**
     * 解密
     */
    public static String jieMi(String param) {
        try {

            // 分割参数
            int splitIndex = param.indexOf('/');
            int packageId = Integer.valueOf(param.substring(0, splitIndex));
            String content = param.substring(splitIndex + 1);

            // 根据ID获取解密的key
            String idKey = idFunction1(packageId, clientKey);

            // 解密
            byte[] byteMi = Base64.getDecoder().decode(content.getBytes());
            SecretKeySpec key = new SecretKeySpec(getKeyBytes(idKey), "DES");
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decryptedData = cipher.doFinal(byteMi);
            return new String(decryptedData);

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("解密失败，param={}", param);
            return "";
        }
    }

    /**
     * 加密
     */
    public static String jiaMi(String packageId, String encryptString) {
        try {

            // 根据ID获取解密的key
            String key = idFunction1(Integer.valueOf(packageId), clientKey);

            SecretKeySpec secretKeySpec = new SecretKeySpec(getKeyBytes(key), "DES");
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            byte[] encryptedData = cipher.doFinal(encryptString.getBytes());
            String encodeStr = Base64.getEncoder().encodeToString(encryptedData);

            // 返回
            return encodeStr;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // key转化为bytes（直接getBytes长度不符合要求）
    private static byte[] getKeyBytes(String key) {
        byte[] bytes = new byte[8];
        byte[] tmp = key.getBytes();
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = i < tmp.length ? tmp[i] : 0;
        }
        return bytes;
    }

    // 抄客户端的
    private static String idFunction1(int converId, String key) {
        int keyLen = key.length();

        long index2 = idFunction2(converId, 1, 0, keyLen);

        long sum = 0;
        for (int j = 0; j < index2; j++) {
            sum += Math.pow(keyLen, j);
        }

        long index3 = converId - sum;

        StringBuilder str = new StringBuilder();
        for (long index = index2 - 1; index >= 0; index--) {
            int temp = (int) (index3 / Math.pow(keyLen, index)) % keyLen;
            str.append(key.charAt(temp));
        }

        return str.toString();
    }

    // 抄客户端的
    private static long idFunction2(long index, long num, long sum, int keyLen) {
        double pow = Math.pow(keyLen, num);
        sum += pow;
        if (sum >= index) {
            return num;
        }
        num++;
        return idFunction2(index, num, sum, keyLen);
    }

}
